package com.topnav.mc.lock;

import com.js.lib.result.Result;
import com.topnav.mc.uitls.TaskLockUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;


/**
 * 同步锁拦截处理器
 */
@Component
@Scope
@Aspect
@Slf4j
public class SyncLockAop {
    @Autowired
    private TaskLockUtil taskLockUtil;


    /**
     * 声明被锁定的方法
     */
    @Pointcut("@annotation(com.topnav.mc.lock.SyncLock)")
    public void begLockMethod() {

    }

    //带注解的对象 syncLock
    @Around(value = "begLockMethod() && @annotation(syncLock)")
    public Object around(ProceedingJoinPoint joinPoint, SyncLock syncLock) throws Throwable {
        String methodName = this.getMethodName(joinPoint);


        if (StringUtils.isEmpty(syncLock.key())){
            return Result.error("@SyncLock 的key 必须被指定 ");
        }
        Class<?> targetCls=joinPoint.getTarget().getClass();
        String targetClsName=targetCls.getName();



        if (taskLockUtil.isLock(syncLock.key())){
            log.error("***** {}：方法 {} 正被锁定",Thread.currentThread().getName(),methodName);
            return Result.error(String.format("***** 方法 %s 正被锁定 ", methodName));
        }

        /** 解锁 */
        taskLockUtil.lock(syncLock.key(),syncLock.dueSec());
        log.info("***** {}：正执行任务 {} ",Thread.currentThread().getName(),methodName);
        Object resultData = null;
        try{
            Object[] args = joinPoint.getArgs();
            resultData = joinPoint.proceed(args);
            return resultData;

        }catch (Exception e){
            if (syncLock.errorUnLock()){
                taskLockUtil.unLock(syncLock.key());
            }
        }finally {
            /** 解锁 */
            taskLockUtil.unLock(syncLock.key());
        }
        return resultData;

    }

    /**
     * 取得方法名
     * @param jp
     * @return
     */
    private String getMethodName(ProceedingJoinPoint jp){
        //1.获取用户行为日志(ip,username,operation,method,params,time,createdTime)
        //获取类的字节码对象，通过字节码对象获取方法信息
        Class<?> targetCls=jp.getTarget().getClass();
        //获取方法签名(通过此签名获取目标方法信息)
        MethodSignature ms=(MethodSignature)jp.getSignature();
        //获取目标方法上的注解指定的操作名称
/*
        Method targetMethod= null;
        try {
            targetMethod = targetCls.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
            //log.info("****** 类名: {}",targetCls.getName());
            //log.info("****** 方法名: {}",ms.getName());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
*/
/*        System.out.println("targetMethod="+targetMethod);
        //获取目标方法名(目标类型+方法名)
        String targetClsName=targetCls.getName();
        String targetObjectMethodName=targetClsName+"."+ms.getName();
        //获取请求参数
        String targetMethodParams=Arrays.toString(jp.getArgs());*/

        return String.format("%s.%s",targetCls.getName(),ms.getName());

    }

}
